package com.bungarus.busi;

import com.bungarus.config.BusiSpringConfig;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * This is the status cache realization based on ehcache version 2, which can use flush() to write disk in real time.
 * Created by jsxiao on 2019/02/25.
 */
public class StatusContainerEhcache2 {
    private static final StatusContainerEhcache2 container = new StatusContainerEhcache2();
    private static final String DISK_STORAGE_PATH = "ehcache.diskStoragePath"; //config name
    private static final String USR_ONLINE_STATUS = "user-online-status";
    private static final int CACHE_ENTRIES_COUNT = 10 * 1000 * 1000;
    private static final long CACHE_OFFHEAP_SIZE = 100;
    private static final long CACHE_DISK_SIZE = 500;

    static ApplicationContext springCtx = new AnnotationConfigApplicationContext(BusiSpringConfig.class);

    private static CacheManager cacheManager = null;
    private Ehcache statusCache;

    private StatusContainerEhcache2() {
        init();
    }

    private void init() {
        System.setProperty(net.sf.ehcache.CacheManager.ENABLE_SHUTDOWN_HOOK_PROPERTY,"true");
        //Create a singleton CacheManager using defaults
        CacheManager cacheManager = CacheManager.create(getClass().getResource("/ehcache.xml"));
        /*
        //Not works (persistence wont't happen) if configured in code this way:
        //Create a Cache specifying its configuration.
        Cache testCache = new Cache(
                new CacheConfiguration(USR_ONLINE_STATUS, CACHE_ENTRIES_COUNT)
                        .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
                        .eternal(true)
                        .timeToLiveSeconds(0)
                        .timeToIdleSeconds(0)
                        .diskExpiryThreadIntervalSeconds(0)
                        .maxBytesLocalDisk(CACHE_DISK_SIZE, MemoryUnit.MEGABYTES)
                        .persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))); //can not set to be RESTARTABLE,which depends on the commercial "BigMemory Go" component
        cacheManager.addCache(testCache);
        */
        this.statusCache = cacheManager.getEhcache(USR_ONLINE_STATUS);
    }

    public static StatusContainerEhcache2 getInstance() {
        return container;
    }

    public static void close() {
        if(null != cacheManager) {
            cacheManager.shutdown();
        }
    }

    /**
     * flush into disk
     */
    public void flush(){
        statusCache.flush();
    }

    /**
     * update user status, NOTICE that here the "userId" is the represent of "{tenantId}:{userId}"
     * @param userId
     * @param status
     * @throws StatusContainerException
     */
    public void put(String userId, Integer status) throws StatusContainerException{
        try {
            this.statusCache.put(new Element(userId, status));
        }
        catch (Exception e) {
            throw new StatusContainerException(e);
        }
    }

    public Integer get(String userId) throws StatusContainerException{
        Integer result=null;
        try {
            Element e = this.statusCache.get(userId);
            if(null != e) {
                result = (Integer)e.getObjectValue();
            }
        }
        catch (Exception e) {
            throw new StatusContainerException(e);
        }
        return result;
    }
}
